package com.wayhome.srpingbootmybatis.fileimportmanager.bo.impl;

import cn.hutool.core.util.IdUtil;
import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.ExcelWriter;
import com.alibaba.excel.write.metadata.WriteSheet;
import com.alibaba.excel.write.style.column.SimpleColumnWidthStyleStrategy;
import com.wayhome.srpingbootmybatis.config.CSPService;
import com.wayhome.srpingbootmybatis.constant.BusinessConst;
import com.wayhome.srpingbootmybatis.exception.CustomerException;
import com.wayhome.srpingbootmybatis.fileimportmanager.bo.ImportFileHandler;
import com.wayhome.srpingbootmybatis.fileimportmanager.dto.ImportFileDTO;
import com.wayhome.srpingbootmybatis.fileimportmanager.dto.ImportFileRlstDTO;
import com.wayhome.srpingbootmybatis.mbs.util.HeadContentCellStyle;
import com.wayhome.srpingbootmybatis.utils.DateUtils;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import java.io.File;
import java.io.InputStream;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.text.SimpleDateFormat;
import java.util.List;

@Slf4j
@Service
public abstract class AbstractImportHandler<T> implements ImportFileHandler {

    private final Class<T> clazz;

    @SuppressWarnings("unchecked")
    public AbstractImportHandler() {
        Type superClass = getClass().getGenericSuperclass();
        this.clazz = (Class<T>) ((ParameterizedType) superClass)
                .getActualTypeArguments()[0];
    }

    @Resource
    protected CSPService cspService;

    @Value("${cos.endpoint}")
    protected String endpoint;

    //所有这类上传参数的文件共用一个桶
    public static final String BUCKET = "batch-query-import-file";

    protected abstract void readFileAndUpload(MultipartFile multipartFile, ImportFileRlstDTO importFileRlstDTO) throws Exception;

    @Override
    public ImportFileRlstDTO doReadImportFile(ImportFileDTO request) throws Exception {
        MultipartFile multipartFile = request.getFile();
        try {
            ImportFileRlstDTO importFileRlstDTO = new ImportFileRlstDTO();
            readFileAndUpload(multipartFile, importFileRlstDTO);

            //设置业务类型
            importFileRlstDTO.setBusinessType(request.getBusinessType());
            //设置业务类型的说明
            importFileRlstDTO.setBusinessMemo(getBusinessMemo());
            //设置文件名称
            importFileRlstDTO.setFileName(multipartFile.getOriginalFilename());
            //设置有效标志
            importFileRlstDTO.setValiFlag(BusinessConst.VALI_FLAG_1_YX);
            //文件大小
            String formatSize = getFormatSize(request.getFile());
            importFileRlstDTO.setFileSize(formatSize);
            //导入状态是成功
            importFileRlstDTO.setImportFlag(BusinessConst.FLAG_1);
            return importFileRlstDTO;
        } catch (Exception e) {
            log.info("==========>解析导入文件时出错：{}", e.getMessage(), e);
            throw new CustomerException("解析文件时发生错误:" + e.getMessage());
        }
    }

    /**
     * 通用的上传，如有特殊需要可自行实现upload方法
     *
     * @param cspPath     文件上传的路径
     * @param tmpFilePath 本地临时用来存放文件的地址
     * @return 返回上传后的文件地址
     * @throws Exception 异常信息
     */
    protected String defaultUploadFile(String cspPath, String tmpFilePath, List<T> successList, List<T> failList) throws Exception {
        //全部成功，就直接把源文件上传上去就行啦
        String filepath = "";

        File localFolder = new File(tmpFilePath);
        if (!localFolder.isDirectory()) {
            localFolder.mkdirs();
        }
        String filename = IdUtil.fastUUID() + ".xlsx";
        String localFilePath = tmpFilePath + filename;
        int sheetNo = 0;
        ExcelWriter excelWriter = EasyExcel.write(localFilePath, clazz)
              .build();
        if (!CollectionUtils.isEmpty(successList)) {
            WriteSheet successSheet = EasyExcel.writerSheet(sheetNo++, "导入成功")
                    .registerWriteHandler(HeadContentCellStyle.myHorizontalCellStyleStrategy())
                    .registerWriteHandler(new SimpleColumnWidthStyleStrategy(20)).build();
            excelWriter.write(successList, successSheet);
        }
        if (!CollectionUtils.isEmpty(failList)) {
            WriteSheet failSheet = EasyExcel.writerSheet(sheetNo, "导入失败")
                    .registerWriteHandler(HeadContentCellStyle.myHorizontalCellStyleStrategy())
                    .registerWriteHandler(new SimpleColumnWidthStyleStrategy(20)).build();
            excelWriter.write(failList, failSheet);
        }
        excelWriter.finish();

        File file = new File(localFilePath);
        filepath = cspService.uploadFile(file, BUCKET, filename, cspPath);
        if (!file.delete()) {
            log.error("fileNamePath：" + localFilePath + "文件删除失败");
        }
        return filepath.replace(endpoint, "");

    }

    /**
     * 获取文件大小（MB为单位，保留2位小数）
     */
    public static double getSizeInMB(MultipartFile file) {
        return Math.round(file.getSize() / (1024.0 * 1024.0) * 100) / 100.0;
    }

    /**
     * 带单位的格式化输出（自动选择B/KB/MB/GB）
     */
    public static String getFormatSize(MultipartFile file) {
        long size = file.getSize();
        if (size < 1024) return size + " B";
        else if (size < 1024 * 1024) return (size / 1024) + " KB";
        else if (size < 1024 * 1024 * 1024) return getSizeInMB(file) + " MB";
        else return (size / (1024 * 1024 * 1024)) + " GB";
    }

    protected boolean canCover2Date(String timeStr) {
        try {
            SimpleDateFormat dateFormat = new SimpleDateFormat(DateUtils.YYYY_MM_DD);
            dateFormat.parse(timeStr);
            return true;
        } catch (Exception e) {
            return false;
        }
    }


    /**
     * 业务说明，由子类实现
     *
     * @return 返回业务说明
     */
    protected abstract String getBusinessMemo();
}
